/**
 * 
 */
package com.ledtechdesign.service;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.ledtechdesign.afcs.IAuthToken;
import com.ledtechdesign.beans.Account;
import com.ledtechdesign.beans.Item;

import com.ledtechdesign.beans.api.IAccountInfo;
import com.ledtechdesign.beans.api.IMeetingInfo;
import com.ledtechdesign.beans.api.IMeetingInfoDescriptor;
import com.ledtechdesign.beans.api.IRepository;
import com.ledtechdesign.service.api.IAFCSServiceResult;
 
/**
 * @author leonardo
 * 
 */
public class AFCSDefaultService<T extends IAFCSServiceResult> implements
		IAFCSService<IAFCSServiceResult> {
 
	private Account account;
	private Map<String, String> authHeaders = new HashMap<String, String>();

	Log logger = LogFactory.getLog(this.getClass());
	private T serviceResult;

	public AFCSDefaultService(Account account, T type) {
		super();
		this.account = account;
		this.serviceResult = type;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ledtechdesign.service.IAFCSService#createRoom(java.lang.String)
	 */
	public IMeetingInfoDescriptor createRoom(IAuthToken authToken, String room)
			throws Exception {
		return this.createRoom(authToken, room, null);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ledtechdesign.service.IAFCSService#createRoom(java.lang.String,
	 * java.lang.String)
	 */
	public IMeetingInfoDescriptor createRoom(IAuthToken authToken, String room,
			String template) throws Exception {
		if (template == null) {
			template = "default";
		}

		String data = "mode=xml&room=" + room + "&template=" + template + "&"
				+ authToken;
		this.logger.debug("Data : " + data);

		this.logger.debug("Posting: " + this.account + " <> " + data + " <> "
				+ this.authHeaders);

		InputStream d = Utils.http_post(this.account.getUrlAndAccount(), data,
				this.authHeaders);

		// new AFCSXMLResult(d)

		return this.serviceResult.createMeetingInfoDescriptor(d);
	}

	public IMeetingInfoDescriptor createTemplate(IAuthToken authToken,
			String room, String basedOn) throws Exception {
		// TODO Auto-generated method stub
		// Not implmeneted yet

		return null;
	}

	public IRepository delete(IAuthToken authToken, String item)
			throws Exception {
		// TODO Auto-generated method stub
		return this.delete(authToken, item, null);
	}

	public IRepository delete(IAuthToken authToken, String item,
			ContainerType containerType) throws Exception {

		if (!IAFCSService.TEMPLATE_ITEMS.equals(containerType)) {
			containerType = IAFCSService.ROOM_ITEMS;
		}

		String data = "action=delete&response=inline&" + authToken;
		InputStream is = Utils.http_post(this.getContentURL() + "/"
				+ containerType + "/" + item, data, this.authHeaders);

		return this.serviceResult.createRepository(is);
	}

	public IRepository deleteRoom(IAuthToken authToken, String item)
			throws Exception {
		// TODO Auto-generated method stub
		return this.delete(authToken, item, IAFCSService.ROOM_ITEMS);
	}

	public IRepository deleteTemplate(IAuthToken authToken, String item)
			throws Exception {
		return this.delete(authToken, item, IAFCSService.TEMPLATE_ITEMS);
	}

    public IAccountInfo getAccountInfo(IAuthToken authToken) throws Exception {
		// TODO Auto-generated method stub

		InputStream data = Utils.http_get(this.account.getUrl()
				+ "app/account?account=" + this.account.getAccid() + "&"
				+ authToken, this.authHeaders);

		return this.serviceResult.createAccountInfo(data);

	}

	String getContentURL() {
		return this.account.getUrl() + IAFCSService.contentAppSegment
				+ this.account.getAccountPath();
	}

	public IAFCSServiceResult getNodes(IAuthToken authToken, String room,
			String path) throws Exception {
		String instance = this.account.getRoomInstanceString().replaceAll(
				"#room#", room);
		InputStream data = Utils.http_get(this.account.getUrl()
				+ "app/cocomo?instance=" + instance + "&path="
				+ this.account.getAccountPath() + "&" + authToken,
				this.authHeaders);

		// TODO rethink
		return null;// new AFCSXMLResult(data);

	}

	public IMeetingInfo getRoomInfo(IAuthToken authToken, String room)
			throws Exception {
		// TODO Auto-generated method stub
		String instance = "";
		if (room.indexOf("/") < 0) {
			// TODO check for NPE getRoomInstanceString
			instance = this.account.getRoomInstanceString().replaceAll(
					"#room#", room);
		}

		InputStream data = Utils.http_get(this.account.getUrl()
				+ "/app/account?instance=" + instance + "&" + authToken,
				this.authHeaders);

		return this.serviceResult.createMeetingInfo(data);
	}

	public IMeetingInfoDescriptor initializationService(IAuthToken authToken,
			Account account) {
		String a = account.getUrlAndAccount();
		IMeetingInfoDescriptor mi = null;
		String b = a + "?mode=xml&accountonly=true&" + authToken;
		InputStream data;
		logger.debug("initializationService:"+b);
		try {
			data = Utils.http_get(b, this.authHeaders);
			
			mi = this.serviceResult.createMeetingInfoDescriptor(data);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return mi;
	}

	public List<Item> listItems(IAuthToken authToken) throws Exception {
		// TODO Auto-generated method stub
		return this.listItems(authToken, ContainerType.ROOM);// this.listItems(authToken,
		// null);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ledtechdesign.service.IAFCSService#listItems(java.lang.String)
	 */
	public List<Item> listItems(IAuthToken authToken, ContainerType type)
			throws Exception {

		if (type != IAFCSService.TEMPLATE_ITEMS)
			type = IAFCSService.ROOM_ITEMS;

		InputStream data = Utils.http_get(this.getContentURL() + "/" + type
				+ "/?" + authToken, this.authHeaders);
		return this.serviceResult.createItemsList(data, type);
	}



	public List<Item> listTemplates(IAuthToken authToken) throws Exception {
		// TODO Auto-generated method stub
		return this.listItems(authToken, ContainerType.TEMPLATE);
	}
	
	public List<Item> listRooms(IAuthToken authToken) throws Exception {
		// TODO Auto-generated method stub
		return this.listItems(authToken, ContainerType.ROOM);
	}

	public String preInitializationService(Account account) {
		String a = account.getUrlAndAccount();

		String b = a + "?mode=xml&accountonly=true";
		InputStream data;

		try {
			data = Utils.http_get(b, this.authHeaders);
			Element result = Utils.parseXML(data);

			if (result.getTagName().equals("result")) {
				if (result.getAttribute("code").equals("unauthorized")) {
					NodeList baseURL = result.getElementsByTagName("baseURL");
					if (baseURL != null) {

						this.account.setUrl(((Element) baseURL.item(0))
								.getAttribute("href"));
					}
					Element authentication = (Element) result
							.getElementsByTagName("authentication").item(0);
					String authURL = authentication.getAttribute("href");
					if (authURL.charAt(0) == '/')
						authURL = this.account.getUrlAndAccount() + authURL;
					return authURL;
				}
			} else {
				throw new Exception("Unexlected result " + result);
			}

		} catch (Exception e) {
			this.logger.debug(e);
		}
		return null;
	}

	public String fetchSessionSecret(IAuthToken authToken,String roomInstanceURI) throws Exception {
		// TODO Auto-generated method stub
		InputStream data = Utils.http_get(this.account.getUrl() + 
				"app/session?instance="
				+ roomInstanceURI + "&" + authToken, authHeaders);

		Element response = Utils.parseXML(data);

		this.logger.debug(Utils.printXML(response));

		Element secret = (Element) response.getElementsByTagName(
				"session-secret").item(0);
		if (secret == null)
			throw new Exception(Utils.printXML(response));

		String sessionSecret = secret.getTextContent().trim();
		this.logger.debug("this Secret is :" + sessionSecret);
		
		return sessionSecret;
	}



}
